package com.wei.czz.framework.rabbitMQ.listener;

import com.wei.czz.common.constant.RedisConstant;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.blog.BlogUserOperationEnum;
import com.wei.czz.common.enums.rabbitMQ.MqEnum;
import com.wei.czz.framework.common.handler.redis.RedisHashHandler;
import com.wei.czz.framework.common.handler.redis.RedisStringHandler;
import com.wei.czz.framework.blog.service.BlogCommentService;
import com.wei.czz.framework.blog.service.BlogService;
import com.wei.czz.framework.blog.service.BlogStatsService;
import com.wei.czz.framework.rabbitMQ.message.blog.BlogOperationMessage;
import com.wei.czz.framework.blog.entity.BlogUserOperationEntity;
import com.wei.czz.framework.blog.service.BlogUserOperationService;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2022-02-25 23:36:40
 * className: BlogOperationQueueListener 博客基本信息修改消息队列监听类
 * version: 1.0
 * description:
 */
@Component
@AllArgsConstructor
public class BlogOperationQueueListener {

    private static final Logger log = LoggerFactory.getLogger(BlogOperationQueueListener.class);

    private final BlogService blogService;

    private final BlogUserOperationService blogUserOperationService;

    private final BlogCommentService blogCommentService;

    private final BlogStatsService blogStatsService;

    private final RedisStringHandler redisStringHandler;

    private final RedisHashHandler redisHashHandler;

    /**
     * 用户操作博客消息监听方法
     * 根据用户操作博客消息对象，更新系统博客基本信息
     *
     * @param blogOperationMessage 用户操作博客消息对象
     */
    @RabbitListener(queues = { MqEnum.Queue.USER_BLOG_OPT, MqEnum.Queue.BLOG_COMMENT })
    public void blogOperationMessage(BlogOperationMessage blogOperationMessage) {
        BlogUserOperationEnum blogUserOperationEnum = BlogUserOperationEnum.getOptType(blogOperationMessage.getOptType());
        if (blogUserOperationEnum == null) {
            log.warn("用户操作博客类型未知，请及时处理。{}", blogOperationMessage);
            return;
        }
        log.info("开始异步更新{}数量业务。{}", blogUserOperationEnum.getDesc(), blogOperationMessage);

        if (blogUserOperationEnum == BlogUserOperationEnum.VIEW_OPT) {

            this.updateBlogViewNum(blogOperationMessage);

        } else if (blogUserOperationEnum == BlogUserOperationEnum.LIKE_OPT) {

            this.updateBlogLikeNum(blogOperationMessage);

        } else if (blogUserOperationEnum == BlogUserOperationEnum.COLLECT_OPT) {

            this.updateBlogCollectNum(blogOperationMessage);

        } else if (blogUserOperationEnum == BlogUserOperationEnum.COMMENT_OPT) {

            this.updateBlogCommentNum(blogOperationMessage);

        }
        // 操作Redis缓存，中保存博客被修改的记录信息
        redisHashHandler.put(RedisConstant.UPDATE_BLOG_MAP, blogOperationMessage.getBlogId().toString(),
                CommonEnum.ONE.getValue());

        log.info("异步更新{}数量业务结束", blogUserOperationEnum.getDesc());
    }

    /**
     * 根据用户操作博客消息对象，修改系统博客浏览量
     *
     * @param blogOperationMessage 用户操作博客消息对象
     */
    private void updateBlogViewNum(BlogOperationMessage blogOperationMessage) {
        Date date = new Date();
        if (!blogOperationMessage.getUpdateUserId().equals(CommonEnum.ZERO.getLongValue())) {
            /*
                如果用户是系统已注册的用户
             */
            // 查询数据库用户操作博客表，匹配用户操作博客记录信息
            List<BlogUserOperationEntity> blogUserOperationList =
                    blogUserOperationService.getBlogUserOperationList(blogOperationMessage);
            if (blogUserOperationList.isEmpty()) {
                BlogUserOperationEntity blogUserOpt = new BlogUserOperationEntity();
                // 设置用户id、博客id、操作类型和操作时间属性值
                blogUserOpt.setUserId(blogOperationMessage.getUpdateUserId())
                        .setBlogId(blogOperationMessage.getBlogId())
                        .setOptType(blogOperationMessage.getOptType())
                        .setOptTime(date);
                // 操作数据库用户操作博客表，保存用户操作博客博客信息
                int count = blogUserOperationService.saveBlogUserOperation(blogUserOpt);
                if (count == 0) {
                    // 中断执行
                    return;
                }
            } else {
                if (blogUserOperationList.size() > 1) {
                    log.warn("系统存在用户关联多条‘浏览’博客记录，请及时处理。{}", blogUserOperationList);
                }
                BlogUserOperationEntity blogUserOpt = blogUserOperationList.get(0);
                // 设置操作时间属性值
                blogUserOpt.setOptTime(date);
                // 操作数据库用户操作博客表，更新用户操作博客记录信息
                int count = blogUserOperationService.updateBlogUserOperation(blogUserOpt);
                if (count == 0) {
                    log.error("修改用户浏览博客记录失败，请务必及时处理");
                    // 中断执行
                    return;
                }
            }
        }
        // 更新博客浏览量值
        int count = blogService.incrementBlogViewNum(blogOperationMessage.getBlogId(), blogOperationMessage.getNum(),
                date, CommonEnum.ZERO.getLongValue());
        if (count == 0) {
            log.error("修改博客浏览数量失败，请务必及时处理");
            return;
        }
        // 增加博客统计的浏览次数
        blogStatsService.incrementBlogViewNum(blogOperationMessage.getBlogId(), blogOperationMessage.getNum());
    }

    /**
     * 根据用户操作博客消息对象，修改系统博客点赞数
     *
     * @param blogOperationMessage 用户操作博客消息对象
     */
    private void updateBlogLikeNum(BlogOperationMessage blogOperationMessage) {
        Date date = new Date();
        // 修改系统博客点赞数
        int count = blogService.updateBlogLikeNum(blogOperationMessage.getBlogId(), blogOperationMessage.getNum(), date,
                blogOperationMessage.getUpdateUserId());
        if (count == 0) {
            log.error("修改博客点赞数量失败，请务必及时处理");
            return;
        }
        if (blogOperationMessage.getNum() > 0) {
            // 增加博客统计的点赞数
            blogStatsService.incrementBlogLikeNum(blogOperationMessage.getBlogId(), blogOperationMessage.getNum());
        } else {
            // 减少博客统计的点赞数
            blogStatsService.decrementBlogLikeNum(blogOperationMessage.getBlogId(), blogOperationMessage.getNum(), blogOperationMessage.getOptTime());
        }
    }

    /**
     * 根据用户操作博客消息对象，修改系统博客收藏量
     *
     * @param blogOperationMessage 用户操作博客消息对象
     */
    private void updateBlogCollectNum(BlogOperationMessage blogOperationMessage) {
        Date date = new Date();
        // 修改系统博客收藏量
        int count = blogService.updateBlogCollectNum(blogOperationMessage.getBlogId(), blogOperationMessage.getNum(), date,
                blogOperationMessage.getUpdateUserId());
        if (count == 0) {
            log.error("修改博客收藏数量失败，请务必及时处理");
            return;
        }
        if (blogOperationMessage.getNum() > 0) {
            // 增加博客统计的收藏数
            blogStatsService.incrementBlogCollectNum(blogOperationMessage.getBlogId(), blogOperationMessage.getNum());
        } else {
            // 减少博客统计的收藏数
            blogStatsService.decrementBlogCollectNum(blogOperationMessage.getBlogId(), blogOperationMessage.getNum(), blogOperationMessage.getOptTime());
        }
    }

    /**
     * 根据用户操作博客消息对象，修改系统博客被评论量
     *
     * @param blogOperationMessage 用户操作博客消息对象
     */
    private void updateBlogCommentNum(BlogOperationMessage blogOperationMessage) {
        // TODO 有删除博客评论的功能代码时，需要重新设置此方法

        Date date = new Date();

        // 查询数据库用户操作博客表，获取用户评论博客记录列表
        List<BlogUserOperationEntity> blogUserOperationList = blogUserOperationService.getBlogUserOperationList(blogOperationMessage);
        int count;
        if (blogUserOperationList.isEmpty()) {
            /*
                没有评论过博客
             */
            BlogUserOperationEntity blogUserOperation = new BlogUserOperationEntity();
            // 设置用户id、博客id、操作类型（‘用户评论’）和操作时间属性值
            blogUserOperation.setUserId(blogOperationMessage.getUpdateUserId())
                    .setBlogId(blogOperationMessage.getBlogId())
                    .setOptType(blogOperationMessage.getOptType())
                    .setOptTime(date);
            // 操作数据库用户操作博客表，新增一条用户操作博客记录信息
            count = blogUserOperationService.saveBlogUserOperation(blogUserOperation);
            if (count == 0) {
                log.error("保存用户操作博客记录信息失败，请务必及时处理");
                // 中断执行
                return;
            }
        } else {
            if (blogUserOperationList.size() > 1) {
                log.warn("用户评论博客记录超过一条，请务必及时处理");
            }
            BlogUserOperationEntity blogUserOperation = blogUserOperationList.get(0);
            blogUserOperation.setOptTime(date);
            // 操作数据库用户操作博客表，更新用户‘评论’博客记录信息
            count = blogUserOperationService.updateBlogUserOperation(blogUserOperation);
            if (count == 0) {
                log.error("修改用户‘评论’博客记录信息，请务必及时处理");
                // 中断执行
                return;
            }
        }
        // 更新博客被评论量值
        count = blogService.updateBlogCommentNum(blogOperationMessage.getBlogId(), blogOperationMessage.getNum(),
                date, CommonEnum.ZERO.getLongValue());
        if (count == 0) {
            log.error("修改博客被评论量值失败，请务必及时处理");
            return;
        }
        if (blogOperationMessage.getBlockId() != null) {
            /*
                评论区块id存在，则更新区块id关联的第一级评论的被回复数量
             */
            count = blogCommentService.updateOneCommentReplyNum(blogOperationMessage.getBlockId(),
                    CommonEnum.ZERO.getValue(), 1);
            if (count == 0) {
                log.error("修改区块id关联的第一级评论的被回复数量失败，请务必及时处理");
            }
        }
        // 增加博客统计的评论数
        blogStatsService.incrementBlogCommentNum(blogOperationMessage.getBlogId(), blogOperationMessage.getNum());

        // 操作Redis缓存，增加系统已发布博客的总评论数量
        redisStringHandler.increment(RedisConstant.COMMENT_COUNT, 1);
    }

}
